--
-- Author:      name
-- DateTime:    2018-04-27 10:59:15
-- Description: 节点间消息转发，服务间消息转发


local skynet = require "skynet"
local log = require "Log"
local cluster = require "cluster"
local config = require "configquery"
require "common"


local NodeMessage = class("NodeMessage")

---------------------------------------------------------
-- private
---------------------------------------------------------
function NodeMessage:ctor()
	self.gateList = nil
	self.gameList = nil
	self.tableList = {}
end

--异步发送消息请求
function NodeMessage:send( node, address, cmd, ... )
	-- print("############", node, address, cmd, ... )
	local ok, result = x_pcall(cluster.send, node, address, cmd, ...)
	if not ok then
		log.error('NodeMessage.send faild:',result)
	end
end

--同步发送消息请求
function NodeMessage:call( node, address, cmd, ... )	
	local ok,result = pcall(cluster.call, node, address, cmd, ...)	
	if not ok then
		log.error("############NodeMessage.call cmd:"..cmd.." faild:", result,node, address, cmd, ...)
		return false
	end
	return result
end

--异步发送到指定节点的.proxy服务
function NodeMessage:sendProxy(node, cmd, ...)
	self:send(node,'.proxy',cmd,...)
end

--同步发送到指定节点的.proxy服务
function NodeMessage:callProxy(node, cmd, ...)
	return self:call(node,'.proxy',cmd,...)
end


--加载gate进程列表
function NodeMessage:loadGateList( )
	if not self.gateList then
		local gate_svrs = config.setting_cfg["gatesvrs"]
		assert(gate_svrs)
		self.gateList = {}
		for k,v in pairs(gate_svrs) do
			if not v.disable  or v.disable ~= 1 then
				table.insert(self.gateList, v)
			end
		end
	end	
end

--加载game进程列表
function NodeMessage:loadGameList()
	if not self.gameList then 
		local game_svrs = config.setting_cfg["gamesvrs"]
		assert(game_svrs)
		self.gameList = {}
		for k,v in pairs(game_svrs) do
			table.insert(self.gameList,v)
		end
	end
end

--获取场次相关配置，游戏名
function NodeMessage:getRoomConfig(tableid)
	local cfgName = getGameConfigName(tableid) --common.lua
	-- print("__________cfgName_________",cfgName)
	if not cfgName then
		return
	end
	if not config[cfgName] then 
		return 
	end
	
	local roomid = getRoomType(tableid)
	return config[cfgName][roomid]
	
end
-----------------------------------------------------------------------------------------
-- public
-----------------------------------------------------------------------------------------





---------------------------------------------------------
-- gate 进程
---------------------------------------------------------
--给所有gate进程主服务发消息
function NodeMessage:sendAllGateManager(cmd,...)
	if not self.gateList then 
		self:loadGateList()
	end
	for k,v in ipairs(self.gateList) do
		self:sendProxy(v.svr_id, cmd,...)
	end
end

--给所有玩家推送消息
function NodeMessage:broadcastAll(msg)
	if not self.gateList then 
		self:loadGateList()
	end
	for k,v in ipairs(self.gateList) do
		self:broadcastGate(v.svr_id, nil, msg)
	end
end

--给所有玩家推送消息
function NodeMessage:broadcastAllGate(ulist,msg)
	if not self.gateList then 
		self:loadGateList()
	end
	for k,v in ipairs(self.gateList) do
		self:broadcastGate(v.svr_id, ulist, msg)
	end
end

--异步发送消息到大厅
function NodeMessage:sendGate(nodename,playerid,cmd,...)
	return self:sendProxy(nodename, 'oper', playerid, cmd, ...)
end

--同步请求发到大厅
function NodeMessage:callGate(nodename,playerid,cmd,...)
	-- print("_________gateName__",nodename)
	-- print(nodename,playerid,cmd,...)
	return self:callProxy(nodename, 'oper', playerid, cmd, ...)
end

--广播给指定用户（一样的消息）
function NodeMessage:broadcastGate(nodename, ulist, msg )
	--ulist 为空时向所有人发推送
	--print("_________#######__",nodename, ulist, msg )
	self:send(nodename, 'broadcasting', 'broad_cast', ulist, msg )
end

--广播给指定用户（一样的消息）
function NodeMessage:callBroadcastGate(nodename, ulist, msg )
	--ulist 为空时向所有人发推送
	--print("_________#######__",nodename, ulist, msg )
	self:call(nodename, 'broadcasting', 'broad_cast', ulist, msg )
end


--同一时间发出指定（用户-消息）对 第个用户的消息可能不一样
function NodeMessage:broadcastGateDiff(nodename, tbPlayerMsg)
	--向所有人发推送
	self:send(nodename, 'broadcasting', 'broadcast_player', tbPlayerMsg)
end



---------------------------------------------------------
-- game 进程
---------------------------------------------------------

--给所有game进程主服务发消息
function NodeMessage:sendAllGameManager(cmd,...)	
	if not self.gameList then 
		self:loadGameList()
	end
	for k,v in pairs(self.gameList) do 
		if v.svr_id then 
			self:sendProxy(v.svr_id, cmd,...)
		else
			log.error('notice_to_game no found ____error')
		end
	end
	return true
end

--同步给桌子发消息
function NodeMessage:callTable(tableid, ...)
	-- local tableCfg = self:getRoomConfig(tableid)
	local nodeName = getNodeNameByTableid(tableid)
	if nodeName then
		return self:callProxy(nodeName,'Request', tableid, ...)
	else
		log.error('_______________table_conf no found tableid:'..tostring(tableid))
	end
end

--异步给桌子发消息
function NodeMessage:sendTable(tableid, ...)
	local nodeName = getNodeNameByTableid(tableid)
	if nodeName then
		return self:sendProxy(nodeName,'Command', tableid, ...)
	else
		log.error('_______________table_conf no found tableid:'..tostring(tableid))
	end
end

--更新玩家属性
function NodeMessage:updateTablePlayer(tableid, playerid, prop_data)
	self:sendTable(tableid,'update_prop',playerid, prop_data)
end


---------------------------------------------------------
-- global 进程
---------------------------------------------------------
--同步给global进程的服务发消息
function NodeMessage:callGlobalService(servicename,cmd,...)
	return self:call('global',servicename,cmd,...)
end

--异步给global进程的服务发消息
function NodeMessage:sendGlobalService(servicename,cmd,...)
	self:send('global',servicename,cmd,...)
end

--同步给global manager服发消息
function NodeMessage:callGlobal(cmd,...)
	return self:callProxy('global',cmd,...)
end

--异步给global manager服发消息
function NodeMessage:sendGlobal(cmd,...)
	self:sendProxy('global',cmd,...)
end

---------------------------------------------------------
-- 同进程服务间发送消息
---------------------------------------------------------

--同步给全局服务发消息
function NodeMessage:callService(servicename,cmd,...)
	-- print("____servicename,",servicename)
	return skynet.call(servicename,'lua',cmd,...)
end

--异步给全局服务发消息
function NodeMessage:sendService(servicename,cmd,...)
	skynet.send(servicename,'lua',cmd,...)
end


return NodeMessage